package desgin.pattern.construtor.singleton;

/**
 * 
 * @Type DoubleCheckSingleton
 * @Desc <b>双检查锁单例 </b><br/>
 *       性能比懒汉式高一些 先检查单例是否已经存在(存在则不需要同步) 如果不存在就同步 , <br/>
 *       在同步块里面再次检查单例是否存在<br/>
 *       ,不存在则创建
 * 
 *       由于volatile关键字可能会屏蔽掉虚拟机中一些必要的代码优化， 所以运行效率并不是很高。因此一般建议，没有特别的需要，不要使用。
 *       也就是说，虽然可以使用“双重检查加锁”机制来实现线程安全的单例， 但并不建议大量采用，可以根据情况来选用<br/>
 *  <br/>
 *       <b>双重检查锁的问题所在</b>:<br/> 这个方法表面上看起来很完美，你只需要付出一次同步块的开销，但它依然有问题。
 *       除非你声明_instance变量时使用了volatile关键字。没有volatile修饰符，
 *       可能出现Java中的另一个线程看到个初始化了一半的_instance的情况，但使用了volatile变量后，
 *       就能保证先行发生关系（happens-before
 *       relationship）。对于volatile变量_instance，所有的写（write） 都将先行发生于读（read），在Java
 *       5之前不是这样，所以在这之前使用双重检查锁有问题。
 * @author shuai.zuo
 * @date 2015年3月6日
 * @Version V1.0
 */
public class DoubleCheckSingleton {
    private volatile static DoubleCheckSingleton instance = null;

    private DoubleCheckSingleton() {
    }

    public static DoubleCheckSingleton getInstance() {
        if (instance == null) {
            synchronized (DoubleCheckSingleton.class) {
                if (instance == null) {
                    instance = new DoubleCheckSingleton();
                }
            }
        }
        return instance;
    }
}
